home *** CD-ROM | disk | FTP | other *** search
/ Aminet 48 / Aminet 48 (2002)(GTI - Schatztruhe)[!][Apr 2002].iso / Aminet / text / edit / vim60src.lha / Vim / vim60 / src / gui_amiga.c < prev    next >
Encoding:
C/C++ Source or Header  |  2001-08-24  |  29.3 KB  |  1,363 lines

  1. /* vi:set ts=8 sts=4 sw=4:
  2.  *
  3.  * VIM - Vi IMproved        by Bram Moolenaar
  4.  *                Amiga GUI support by Michael Nielsen
  5.  *
  6.  * Do ":help uganda"  in Vim to read copying and usage conditions.
  7.  * Do ":help credits" in Vim to see a list of people who contributed.
  8.  * See README.txt for an overview of the Vim source code.
  9.  */
  10.  
  11. #include <stdlib.h>
  12. #include <string.h>
  13. #include <exec/types.h>
  14. #include <intuition/intuition.h>
  15. #include <utility/tagitem.h>
  16. #include <graphics/text.h>
  17. #include <graphics/rastport.h>
  18. #include <graphics/layers.h>
  19. #include <proto/intuition.h>
  20. #include <proto/graphics.h>
  21. #include <proto/layers.h>
  22. #include <assert.h>
  23. #include "gui_amiga.h"
  24. #include "vim.h"
  25. #include <math.h>
  26. #include <limits.h>
  27.  
  28. #include "version.h"
  29.  
  30. #if defined(FEAT_GUI_AMIGA) || defined(PROTO)
  31.  
  32. #define KEYUP 76
  33. #define KEYDOWN 77
  34. #define KEYRIGHT 78
  35. #define KEYLEFT 79
  36.  
  37. /* When generating prototypes on Unix, these need to be defined */
  38. #ifdef PROTO
  39. # define STRPTR char *
  40. #endif
  41.  
  42. static struct PropInfo Gadget2SInfo = { AUTOKNOB+PROPBORDERLESS, (unsigned short)-1, (unsigned short)-1, 6553, 6553, };
  43. static struct Image Image1 = { 0, 0, 10, 397,    0, NULL, 0x0000, 0x0000, NULL };
  44. static struct Gadget propGadget = { NULL, -12, 15, 10, -28,
  45.     GFLG_RELRIGHT+GFLG_RELHEIGHT,
  46.     GACT_RELVERIFY+GACT_RIGHTBORDER+GACT_IMMEDIATE,
  47.     GTYP_PROPGADGET+GTYP_GZZGADGET,
  48.     (APTR)&Image1, NULL,
  49.     NULL, NULL, (APTR)&Gadget2SInfo, NULL, NULL };
  50.  
  51. struct GFXBase        *gfxBase;
  52. struct ExecBase        *execBase;
  53. struct LayersBase    *layersBase;
  54.  
  55. struct TagItem tags[] =
  56. {
  57.     {WA_Left, 0},
  58.     {WA_Top, 0},
  59.     {WA_Width, 400},
  60.     {WA_Height, 400},
  61.     {WA_Title, (ULONG)VIM_VERSION_SHORT},
  62.     {WA_ScreenTitle, (ULONG)VIM_VERSION_LONG},
  63.     {WA_DragBar, TRUE},            /* enable dragging of the window */
  64.     {WA_DepthGadget, TRUE},        /* enable the depth gadget */
  65.     {WA_CloseGadget, TRUE},        /* enable the close gadget*/
  66.     {WA_SizeGadget, TRUE},        /* enable the size gadget */
  67.     {WA_SizeBBottom, TRUE},        /* sizegadget contained in bottom border */
  68.     {WA_SmartRefresh, TRUE},        /* choose smart refresh, saves us doing a lot of work */
  69.     {WA_ReportMouse, TRUE},        /* Report the position of the mouse */
  70.     {WA_GimmeZeroZero, TRUE},
  71.     {WA_Activate, TRUE},        /* Activate window on startup */
  72.     {WA_Activate, TRUE},        /* Activate window on startup */
  73.     {WA_NoCareRefresh, TRUE},        /* Refresh screen, don't tell us */
  74.     {WA_NewLookMenus, TRUE},        /* use the new options for the menu */
  75.     {WA_AutoAdjust, TRUE},        /* If window is too big for screen adjust size*/
  76.     {WA_NoCareRefresh, TRUE},        /* If window is too big for screen adjust size*/
  77.     {WA_MouseQueue, 1},            /* Limit number of pending mouse movement*/
  78.     {WA_RptQueue, 10},            /* Limit number of pending keystrokes*/
  79.     {WA_IDCMP,                /* IDCMP, what events interest us  */
  80.     IDCMP_NEWSIZE            /* Notify us about size change of window*/
  81.         |IDCMP_REFRESHWINDOW    /* Notify us when the window needs refreshing */
  82.         |IDCMP_MOUSEBUTTONS        /* Notify us when the mouse buttons have been used */
  83.         |IDCMP_MOUSEMOVE        /* Notify us when the mouse is moving */
  84.         |IDCMP_GADGETDOWN        /* Notify us when a gadget has been selected */
  85.         |IDCMP_GADGETUP        /* Notify us when a gadget has been released */
  86.         |IDCMP_MENUPICK        /* Notify us when a menu has been picked */
  87.         |IDCMP_CLOSEWINDOW        /* Notify us when the user tries to close the window */
  88.         |IDCMP_VANILLAKEY        /* Notify us about keystrokes */
  89.         |IDCMP_RAWKEY        /* Notify us when raw key events have been used, ie cursor*/
  90.         |IDCMP_INTUITICKS        /* Simpler timer for the blink option */
  91.         |IDCMP_MENUHELP        /* Allow the help key to be used during menu events */
  92.         |IDCMP_GADGETHELP        /* Allow the help key to be used during gadget events */
  93.         |IDCMP_INACTIVEWINDOW    /* notify of inactive window */
  94.         |IDCMP_ACTIVEWINDOW        /* notify of inactive window */
  95.     },
  96.     {TAG_DONE, NULL}
  97. };
  98.  
  99. #if defined(D)
  100. #undef D
  101. #endif
  102.  
  103. /*#define D(_msg) fprintf(stderr, "%s\n", _msg)*/
  104.  
  105. #define D(_A)
  106.  
  107. static void AmigaError(const char *string);
  108.  
  109. void HandleEvent(unsigned long * object);
  110.  
  111. static struct NewWindow vimNewWindow =
  112. {
  113.     0, 0,        /* window XY origin relative to TopLeft of screen */
  114.     0, 0,        /* window width and height */
  115.     0, 1,        /* detail and block pens */
  116.     NULL,        /* IDCMP flags */
  117.     NULL,        /* other window flags */
  118.     &propGadget,    /* first gadget in gadget list */
  119.     NULL,        /* custom CHECKMARK imagery */
  120.     "Amiga Vim gui",    /* window title */
  121.     NULL,        /* custom screen pointer */
  122.     NULL,        /* custom bitmap */
  123.     50, 50,        /* minimum width and height */
  124.     (unsigned short)-1, (unsigned short)-1,    /* maximum width and height */
  125.     WBENCHSCREEN    /* destination screen type */
  126. };
  127.  
  128. static struct
  129. {
  130.     unsigned int  key_sym;
  131.     char_u  vim_code0;
  132.     char_u  vim_code1;
  133. } special_keys[] =
  134. {
  135.     {0,            0, 0}
  136. };
  137.  
  138. #if 0
  139.     /* not used? */
  140.     static int
  141. hex_digit(int c)
  142. {
  143.     if (isdigit(c))
  144.     return c - '0';
  145.     c = TO_LOWER(c);
  146.     if (c >= 'a' && c <= 'f')
  147.     return c - 'a' + 10;
  148.     return -1000;
  149. }
  150. #endif
  151.  
  152. static int characterWidth = -1;
  153. static int characterHeight = -1;
  154. static struct
  155. {
  156.     BOOL    active;
  157.     enum
  158.     {
  159.     CursorOff,
  160.     CursorOn,
  161.     CursorWait
  162.     }        state;
  163.     int        onTime;
  164.     int        offTime;
  165.     int        waitTime;
  166.     int        current;
  167. } cursor =
  168. {
  169.     TRUE,
  170.     CursorWait,
  171.     10,
  172.     10,
  173.     7,
  174.     0
  175. };
  176.  
  177. enum DrawBoxMode
  178. {
  179.     DB_Filled,
  180.     DB_NotFilled
  181. };
  182.  
  183.     static void
  184. TextDimensions(void)
  185. {
  186.     struct TextExtent textExt;
  187.  
  188.     TextExtent(gui.window->RPort, "s", 1, &textExt);
  189.  
  190.     characterWidth = textExt.te_Width;
  191.     characterHeight = textExt.te_Height;
  192. }
  193.  
  194.     static int
  195. posWidthCharToPoint(int width)
  196. {
  197.     return (width)*characterWidth;
  198. }
  199.  
  200.     static int
  201. posHeightCharToPoint(int height)
  202. {
  203.     return (int)(height+1)*characterHeight;
  204. }
  205.  
  206.     static int
  207. posWidthPointToChar(int width)
  208. {
  209.     return (int)floor((float)width/(float)characterWidth)-1;
  210. }
  211.  
  212.     static int
  213. posHeightPointToChar(int height)
  214. {
  215.     return (int)floor((float)height/(float)characterHeight)-2;
  216. }
  217.  
  218.     static int
  219. widthCharToPoint(int width)
  220. {
  221.     return (width)*(characterWidth);
  222. }
  223.  
  224.     static int
  225. heightCharToPoint(int height)
  226. {
  227.     return (height)*characterHeight;
  228. }
  229.  
  230.     static int
  231. widthPointToChar(int width)
  232. {
  233.     return width/characterWidth+13;
  234. }
  235.  
  236.     static int
  237. heightPointToChar(int height)
  238. {
  239.     return height/characterHeight - 3;
  240. }
  241.  
  242.     static void
  243. refreshBorder(void)
  244. {
  245.     /*WaitBOVP(gui.window->);*/
  246.     RefreshWindowFrame(gui.window);
  247. }
  248.  
  249.     static void
  250. drawBox(enum DrawBoxMode mode, unsigned short col, unsigned short row, guicolor_T color)
  251. {
  252.     /*
  253.        SetDrMd(gui.window->RPort, COMPLEMENT);
  254.        SetAPen(gui.window->RPort, -1);
  255.        SetBPen(gui.window->RPort, -1);
  256.        Move(gui.window->RPort, posWidthCharToPoint(col), posHeightCharToPoint(row));
  257.        Text(gui.window->RPort, " ", 1);
  258.        SetDrMd(gui.window->RPort, JAM2);
  259.      */
  260. }
  261.  
  262.     static enum event
  263. EventHandler(void)
  264. {
  265.     struct IntuiMessage *msg;
  266.     enum event        returnEvent;
  267.     int            class, code;
  268.     static int        dragging = 0;
  269.     static int        mouseX, mouseY;
  270.     char_u        string[40];
  271.  
  272.     msg = (struct IntuiMessage *)GetMsg(gui.window->UserPort);
  273.  
  274.     if (!msg)
  275.     {
  276.     returnEvent = ev_NullEvent;
  277.     }
  278.     else
  279.     {
  280.  
  281.     class = msg->Class;
  282.     code = msg->Code;
  283.  
  284.     switch(class)
  285.     {
  286.         case IDCMP_INTUITICKS:
  287.         /*
  288.            if (cursor.active)
  289.            {
  290.            cursor.current ++;
  291.            if (cursor.state == CursorOff)
  292.            {
  293.            printf("cursor turned on\n");
  294.            if (cursor.offTime < cursor.current)
  295.            {
  296.            gui_undraw_cursor();
  297.            cursor.state = CursorOn;
  298.            cursor.current = 0;
  299.            }
  300.            }
  301.            else if (cursor.state == CursorOn)
  302.            {
  303.            printf("cursor turned off\n");
  304.            if (cursor.onTime < cursor.current)
  305.            {
  306.            cursor.state = CursorOff;
  307.            gui_update_cursor(FALSE);
  308.            cursor.current = 0;
  309.            }
  310.            }
  311.            else if (cursor.state == CursorWait)
  312.            {
  313.            printf("cursor turned Wait\n");
  314.            if (cursor.waitTime < cursor.current)
  315.            {
  316.            cursor.state = CursorOn;
  317.            cursor.current = 0;
  318.            }
  319.     }
  320.     }
  321.            else
  322.            {
  323.            }
  324.            returnEvent = ev_IntuiTicks;
  325.            */
  326.                break;
  327.         case IDCMP_MOUSEBUTTONS:
  328.            {
  329.                int vim_modifiers=0;
  330.                D("Mouse button event detected");
  331.                switch (msg->Qualifier )
  332.                {
  333.                case IEQUALIFIER_LSHIFT:
  334.                case IEQUALIFIER_RSHIFT:
  335.                    D("detected a shift key");
  336.                    vim_modifiers|=MOUSE_SHIFT;
  337.                    break;
  338.                case IEQUALIFIER_CONTROL:
  339.                    D("detected a Control key");
  340.                    vim_modifiers |= MOUSE_CTRL;
  341.                    break;
  342.                }
  343.                if (code == SELECTDOWN)
  344.                {
  345.                D("Select Down detected\n");
  346.                dragging = 1;
  347.                gui_send_mouse_event(MOUSE_LEFT,
  348.                    posWidthPointToChar(mouseX = msg->MouseX),
  349.                    posHeightPointToChar(mouseY = msg->MouseY),
  350.                    FALSE,
  351.                    vim_modifiers);
  352.                /*gui_start_highlight(HL_ALL);*/
  353.                }
  354.                else if (code == SELECTUP)
  355.                {
  356.                D("Select UP detected\n");
  357.                dragging = 0;
  358.                gui_send_mouse_event(MOUSE_RELEASE,
  359.                    posWidthPointToChar(msg->MouseX),
  360.                    posHeightPointToChar(msg->MouseY),
  361.                    FALSE, vim_modifiers);
  362.                /*gui_stop_highlight(mask);*/
  363.                }
  364.                returnEvent = ev_MouseButtons;
  365.                break;
  366.            }
  367.         case IDCMP_MOUSEMOVE:
  368.            if ((abs(mouseX-msg->MouseX) > characterWidth) || (abs(mouseY-msg->MouseY)>characterHeight))
  369.            {
  370.                mouseX = msg->MouseX;
  371.                mouseY = msg->MouseY;
  372.                if (!dragging)
  373.                {
  374.                gui_send_mouse_event(MOUSE_SETPOS, posWidthPointToChar(msg->MouseX), posHeightPointToChar(msg->MouseY), FALSE, 0);
  375.                break;
  376.                }
  377.                else
  378.                {
  379.                D("dragging\n");
  380.                gui_send_mouse_event(MOUSE_DRAG, posWidthPointToChar(msg->MouseX), posHeightPointToChar(msg->MouseY), FALSE, 0);
  381.                }
  382.            }
  383.            returnEvent = ev_MouseMove;
  384.            break;
  385.         case IDCMP_VANILLAKEY:
  386.            {
  387.                string[0] = (char_u)code;
  388.                if (code == CSI)
  389.                {
  390.                /* Insert CSI as K_CSI.  Untested! */
  391.                string[1] = KS_EXTRA;
  392.                string[2] = (int)KE_CSI;
  393.                add_to_input_buf(string, 3);
  394.                }
  395.                else
  396.                {
  397.                int    len = 1;
  398.  
  399.                if (input_conv.vc_type != CONV_NONE)
  400.                    len = convert_input(string, 1, sizeof(string));
  401.                add_to_input_buf(string, len);
  402.                }
  403.                returnEvent = ev_KeyStroke;
  404.                break;
  405.                case IDCMP_RAWKEY:
  406.                if (msg->Qualifier & IEQUALIFIER_LSHIFT)
  407.                {
  408.                }
  409.                else if (msg->Qualifier & IEQUALIFIER_RSHIFT)
  410.                {
  411.                }
  412.                else if (msg->Qualifier & IEQUALIFIER_CONTROL)
  413.                {
  414.                if (code == 33)
  415.                {
  416.                    trash_input_buf();
  417.                }
  418.                }
  419.                else if (msg->Code == KEYUP)
  420.                {
  421.                string[0] = CSI;
  422.                string[1] = 'k';
  423.                string[2] = 'u';
  424.                add_to_input_buf(string, 3);
  425.                }
  426.                else if (msg->Code == KEYLEFT)
  427.                {
  428.                string[0] = CSI;
  429.                string[1] = 'k';
  430.                string[2] = 'l';
  431.                add_to_input_buf(string, 1);
  432.                }
  433.                else if (msg->Code == KEYRIGHT)
  434.                {
  435.                string[0] = CSI;
  436.                string[1] = 'k';
  437.                string[2] = 'r';
  438.                add_to_input_buf(string, 1);
  439.                }
  440.                else if (msg->Code == KEYDOWN)
  441.                {
  442.                string[0] = CSI;
  443.                string[1] = 'k';
  444.                string[2] = 'd';
  445.                add_to_input_buf(string, 1);
  446.                }
  447.                returnEvent = ev_KeyStroke;
  448.                break;
  449.            }
  450.         case IDCMP_MENUVERIFY:
  451.            returnEvent = ev_MenuVerify;
  452.            /* Menu verification requested */
  453.            switch (code)
  454.            {
  455.                case MENUWAITING:
  456.                /*
  457.                 ** It's not for us, the user is accessing another
  458.                 ** programs menu, this is a good time to do some
  459.                 ** cleanup etc
  460.                 */
  461.                break;
  462.                case MENUHOT:
  463.                /*
  464.                 ** It is our menu that is going hot, we have kontrol
  465.                 ** Menu action can be cancelled by
  466.                 ** msg->Code = MENUCANCEL;
  467.                 */
  468.                break;
  469.                default:
  470.                break;
  471.            }
  472.            break;
  473.         case IDCMP_MENUPICK:
  474.            returnEvent = ev_MenuPick;
  475.            {
  476.                /*
  477.             ** one of our menu's have been selected, let's find out which
  478.             */
  479.                union myMenuItemUnion *item;
  480.                int menuNumber;
  481.  
  482.                menuNumber = code;
  483.  
  484.                item = (union myMenuItemUnion *) ItemAddress(gui.menu, menuNumber);
  485.  
  486.  
  487.                if (item)
  488.                {
  489.                gui_menu_cb(item->myMenuItem.guiMenu);
  490.                }
  491.            }
  492.            break;
  493.         case IDCMP_CLOSEWINDOW:
  494.            {
  495.                gui_mch_exit(1);
  496.                break;
  497.            }
  498.         case IDCMP_NEWSIZE:
  499.            {
  500.                int cx, cy;
  501.                cx = widthPointToChar(gui.window->Width);
  502.                cy = heightPointToChar(gui.window->Height);
  503.  
  504.                gui_resize_shell(cx, cy);
  505.  
  506.                returnEvent = ev_NewSize;
  507.                break;
  508.            }
  509.         case IDCMP_REFRESHWINDOW:
  510.            refreshBorder();
  511.            returnEvent = ev_RefreshWindow;
  512.            break;
  513.         case IDCMP_GADGETDOWN:
  514.            returnEvent = ev_GadgetDown;
  515.            break;
  516.         case IDCMP_GADGETUP:
  517.            returnEvent = ev_GadgetUp;
  518.            break;
  519.         case IDCMP_MENUHELP:
  520.            returnEvent = ev_MenuHelp;
  521.            break;
  522.         case IDCMP_GADGETHELP:
  523.            returnEvent = ev_GadgetHelp;
  524.            break;
  525.         case IDCMP_INACTIVEWINDOW:
  526.            gui.in_focus = FALSE;
  527.         case IDCMP_ACTIVEWINDOW:
  528.            gui.in_focus = TRUE;
  529.            gui_update_cursor(TRUE, FALSE);
  530.            break;
  531.         default:
  532.            break;
  533.     }
  534.     ReplyMsg((struct Message*)msg);
  535.     }
  536.  
  537.     return returnEvent;
  538.     /* mouse positin gui.window->MoseY, gui.window->MouseX) */
  539. }
  540.  
  541.     static int
  542. checkEventHandler(void)
  543. {
  544.     enum event happened;
  545.  
  546.     do
  547.     {
  548.     happened = EventHandler() ;
  549.     }
  550.     while  (happened != ev_NullEvent);
  551.  
  552.     return OK;
  553. }
  554.  
  555.     static int
  556. charEventHandler(int wtime)
  557. {
  558.     enum event happened;
  559.     int rc;
  560.  
  561.     do
  562.     {
  563.     Wait(1<<gui.window->UserPort->mp_SigBit);
  564.  
  565.     happened = EventHandler() ;
  566.     }
  567.     while ((happened != ev_IntuiTicks) && (happened != ev_KeyStroke) && (happened != ev_MenuPick) && (happened != ev_MouseMove) &&(happened != ev_MouseButtons) );
  568.  
  569.     if (happened == ev_KeyStroke || happened == ev_MenuPick)
  570.     rc = OK;
  571.     else
  572.     rc = FAIL;
  573.  
  574.     return rc;
  575. }
  576.  
  577.  
  578. /*
  579.  * add primary menu
  580.  */
  581.     void
  582. gui_mch_add_menu_item(vimmenu_T *menu, int idx)
  583. {
  584.     union myMenuItemUnion *menuItemUnion = NULL;
  585.     struct IntuiText *menutext = NULL;
  586.     vimmenu_T *parent;
  587.  
  588.     assert(menu != NULL);
  589.     assert(menu->parent != NULL);
  590.     parent = menu->parent;
  591.  
  592.     /* Don't add menu separator */
  593.     if (menu_is_separator(menu->name))
  594.     return;
  595.  
  596.     if (parent->menuItemPtr == NULL)
  597.     return;
  598.  
  599.     /* TODO: use menu->mnemonic and menu->actext */
  600.     menutext = (struct IntuiText *) malloc(sizeof(struct IntuiText));
  601.  
  602.     SetAttrib(menutext, FrontPen, 3);
  603.     SetAttrib(menutext, BackPen, 1);
  604.     SetAttrib(menutext, DrawMode, COMPLEMENT);
  605.     SetAttrib(menutext, LeftEdge, 0);
  606.     SetAttrib(menutext, TopEdge, 0);
  607.     SetAttrib(menutext, ITextFont, NULL);
  608.     SetAttrib(menutext, NextText, NULL);
  609.  
  610.     menuItemUnion = malloc(sizeof(*menuItemUnion));
  611.  
  612.     SetAttrib(&menuItemUnion->menuItem, NextItem, parent->menuItemPtr);
  613.     SetAttrib(&menuItemUnion->menuItem, LeftEdge, 0);
  614.     SetAttrib(&menuItemUnion->menuItem, Width, characterWidth*strlen(menu->dname));
  615.     SetAttrib(&menuItemUnion->menuItem, Height, characterHeight+2);
  616.     SetAttrib(&menuItemUnion->menuItem, Flags, ITEMTEXT+ITEMENABLED+HIGHCOMP);
  617.     SetAttrib(&menuItemUnion->menuItem, MutualExclude, 0);
  618.     SetAttrib(&menuItemUnion->menuItem, ItemFill, (APTR)menutext);
  619.     SetAttrib(&menuItemUnion->menuItem, SelectFill, NULL);
  620.     SetAttrib(&menuItemUnion->menuItem, Command, NULL);
  621.     SetAttrib(&menuItemUnion->menuItem, SubItem, NULL);
  622.     SetAttrib(&menuItemUnion->menuItem, NextSelect, MENUNULL);
  623.  
  624.     menutext->IText = malloc(strlen(menu->dname) + 1);
  625.  
  626.     strcpy(menutext->IText, menu->dname);
  627.  
  628.     menuItemUnion->menuItem.NextItem = NULL;
  629.  
  630.  
  631.     if (parent)
  632.     {
  633.     if (!parent->menuItemPtr)
  634.     {
  635.         D("Adding first subElement");
  636.         SetAttrib(&menuItemUnion->menuItem, TopEdge, 0);
  637.         parent->menuPtr->FirstItem = &menuItemUnion->menuItem;
  638.         parent->menuItemPtr = &menuItemUnion->menuItem;
  639.     }
  640.     else
  641.     {
  642.         struct MenuItem *tmpMenuItem;
  643.         tmpMenuItem = parent->menuItemPtr;
  644.         while (tmpMenuItem->NextItem)
  645.         {
  646.         tmpMenuItem = tmpMenuItem->NextItem;
  647.         }
  648.         tmpMenuItem->NextItem = &menuItemUnion->menuItem;
  649.         SetAttrib(&menuItemUnion->menuItem, TopEdge, tmpMenuItem->TopEdge+tmpMenuItem->Height);
  650.     }
  651.     }
  652.     menu->menuPtr= NULL;
  653.     menu->menuItemPtr = &menuItemUnion->menuItem;
  654.     menuItemUnion->myMenuItem.guiMenu = menu;
  655. }
  656.  
  657.  
  658.     static struct Menu *
  659. getMenu(struct RastPort *rast, int left, STRPTR name)
  660. {
  661.     struct Menu *menu;
  662.     struct TextExtent textExt;
  663.  
  664.     menu = malloc(sizeof(*menu));
  665.     menu->NextMenu = NULL;
  666.     menu->LeftEdge = left;
  667.  
  668.     TextExtent(rast, name, strlen(name), &textExt);
  669.  
  670.     menu->TopEdge = 0;
  671.     menu->Width = textExt.te_Width;
  672.     menu->Height = textExt.te_Height;
  673.     menu->Flags = ITEMTEXT+HIGHCOMP+MENUENABLED;
  674.     menu->MenuName = name;
  675.     menu->FirstItem = NULL;
  676.  
  677.     return menu;
  678. }
  679.  
  680. /*
  681.  * add  1st level submenu item
  682.  */
  683.     void
  684. gui_mch_add_menu(vimmenu_T *menu, int idx)
  685. {
  686.     struct Menu    *newMenu;
  687.     int        pos = 0;
  688.  
  689.     if (!menu_is_menubar(menu->name))
  690.     return;
  691.  
  692.     menu->menuPtr = newMenu = getMenu(gui.window->RPort, 0, menu->dname);
  693.     menu->menuItemPtr = NULL;
  694.     newMenu->NextMenu = NULL;
  695.  
  696.     if (!gui.menu)
  697.     {
  698.     D("Adding head menu");
  699.     gui.menu = newMenu ;
  700.     }
  701.     else
  702.     {
  703.     struct Menu *tmpMenu;
  704.  
  705.     tmpMenu = gui.menu;
  706.     while (tmpMenu->NextMenu)
  707.         tmpMenu = tmpMenu->NextMenu;
  708.     tmpMenu->NextMenu = newMenu;
  709.     pos = tmpMenu->LeftEdge +
  710.         TextLength(gui.window->RPort, tmpMenu->MenuName,
  711.             strlen(tmpMenu->MenuName));
  712.     newMenu->LeftEdge = pos;
  713.     }
  714. }
  715.  
  716.     void
  717. gui_mch_toggle_tearoffs(enable)
  718.     int        enable;
  719. {
  720.     /* no tearoff menus */
  721. }
  722.  
  723.     int
  724. gui_mch_set_blinking(long wait, long on, long off)
  725. {
  726.     cursor.waitTime = wait/100;
  727.     cursor.onTime = on/100;
  728.     cursor.offTime = off/100;
  729.     return OK;
  730. }
  731.  
  732.     void
  733. gui_mch_prepare(int *argc, char **argv)
  734. {
  735.     D("gui_mch_prepare");
  736.  
  737.     execBase = (struct ExecBase *)OpenLibrary("exec.library", NULL);
  738.     gfxBase = (struct GFXBase *)OpenLibrary("graphics.library", NULL);
  739.     layersBase = (struct LayersBase *)OpenLibrary("layers.library", NULL);
  740.  
  741.     if (!execBase)
  742.     {
  743.     D("Cannot open exec.library, aborting");
  744.     }
  745.     if (!gfxBase)
  746.     {
  747.     D("Cannot open graphics.library, aborting");
  748.     }
  749.     if (!layersBase)
  750.     {
  751.     D("Cannot open graphics.library, aborting");
  752.     }
  753.     D("gui_mch_prepare done ");
  754. }
  755.  
  756.     void
  757. atexitDoThis(void)
  758. {
  759.     gui_mch_exit(-1);
  760. }
  761.  
  762. /*
  763.  * Check if the GUI can be started.  Called before gvimrc is sourced.
  764.  * Return OK or FAIL.
  765.  */
  766.     int
  767. gui_mch_init_check(void)
  768. {
  769.     if (execBase && gfxBase && layersBase)
  770.     return OK;
  771.     return FAIL;
  772. }
  773.  
  774.     int
  775. gui_mch_init(void)
  776. {
  777.     int returnCode = FAIL; /* assume failure*/
  778.  
  779.     gui.window = OpenWindowTagList(&vimNewWindow, tags);
  780.     if (gui.window)
  781.     {
  782.     gui.in_use = TRUE;
  783.     gui.in_focus=TRUE;
  784.     SetDrMd(gui.window->RPort, JAM2);
  785.     atexit(atexitDoThis);
  786.     TextDimensions();
  787.     returnCode = OK; /* we've had sucess */
  788.     if (gui_win_x != -1 && gui_win_y != -1)
  789.         gui_mch_set_winpos(gui_win_x, gui_win_y)
  790.     }
  791.     gui.menu = NULL;
  792.  
  793.     return returnCode;
  794. }
  795.  
  796.     void
  797. gui_mch_new_colors(void)
  798. {
  799.     D("gui_mch_new_colors");
  800. }
  801.  
  802.     int
  803. gui_mch_open(void)
  804. {
  805.     D("gui_mch_open");
  806.  
  807.     return OK;
  808. }
  809.  
  810.     void
  811. gui_mch_exit(int returnCode)
  812. {
  813.     D("****gui_mch_exit");
  814.     if (gui.window)
  815.     {
  816.     D("Closeing window ");
  817.     CloseWindow(gui.window);
  818.     CloseLibrary((struct Library*)execBase);
  819.     CloseLibrary((struct Library*)gfxBase);
  820.     gui.window = NULL;
  821.     gui.in_use = FALSE;
  822.     getout(1);
  823.     }
  824. }
  825.  
  826. /*
  827.  * Get the position of the top left corner of the window.
  828.  */
  829.     int
  830. gui_mch_get_winpos(int *x, int *y)
  831. {
  832.     /* TODO */
  833.     return FAIL;
  834. }
  835.  
  836. /*
  837.  * Set the position of the top left corner of the window to the given
  838.  * coordinates.
  839.  */
  840.     void
  841. gui_mch_set_winpos(int x, int y)
  842. {
  843.     /* TODO */
  844. }
  845.  
  846.     void
  847. gui_mch_set_shellsize(int width, int height,
  848.     int min_width, int min_height, int base_width, int base_height)
  849. {
  850.     D("gui_mch_set_shellsize");
  851.  
  852.     ChangeWindowBox(gui.window, gui.window->TopEdge,
  853.         gui.window->LeftEdge, widthCharToPoint(width),
  854.         heightCharToPoint(height));
  855.     checkEventHandler();
  856. }
  857.  
  858.     void
  859. gui_mch_get_screen_dimensions(int *screen_w, int *screen_h)
  860. {
  861.     *screen_w = widthPointToChar(gui.window->Width);
  862.     *screen_h = heightPointToChar(gui.window->Height);
  863. }
  864.  
  865.     void
  866. gui_mch_set_text_area_pos(int x, int y, int w, int h)
  867. {
  868.     D("gui_mch_set_text_area_pos");
  869. }
  870.  
  871.     void
  872. gui_mch_enable_scrollbar(scrollbar_T *sb, int flag)
  873. {
  874.     /* done by default */
  875.     /* TODO: disable scrollbar when it's too small */
  876. }
  877.  
  878.     void
  879. gui_mch_set_scrollbar_thumb(scrollbar_T *sb, long val, long size, long max)
  880. {
  881. }
  882.  
  883.     void
  884. gui_mch_set_scrollbar_pos(scrollbar_T *sb, int x, int y, int w, int h)
  885. {
  886.     D("gui_mch_set_scrollbar_pos");
  887.     /*NewModifyProp(&propGadget, gui.window, NULL, MAXPOT, MAXPOT/sb->max*y, MAXPOT, MAXBODY/sb->max/sb->size, 1);*/
  888. }
  889.  
  890.     void
  891. gui_mch_create_scrollbar(scrollbar_T *sb, int orient)
  892. {
  893.     /* this is done by default */
  894. }
  895.  
  896. #if defined(FEAT_WINDOWS) || defined(PROTO)
  897.     void
  898. gui_mch_destroy_scrollbar(scrollbar_T *sb)
  899. {
  900.     /* this is done by default */
  901. }
  902. #endif
  903.  
  904. int gui_mch_init_font(char_u *font_name, int fontset)
  905. {
  906.     /*D("gui_mch_init_font");*/
  907.     return OK;
  908. }
  909.  
  910.     int
  911. gui_mch_adjust_charsize()
  912. {
  913.     return FAIL;
  914. }
  915.  
  916.     GuiFont
  917. gui_mch_get_font( char_u *name, int giveErrorIfMissing)
  918. {
  919.     /*D("gui_mch_get_font");*/
  920.     return NULL;
  921. }
  922.  
  923.     void
  924. gui_mch_set_font(GuiFont font)
  925. {
  926.     /*D("gui_mch_set_font");*/
  927. }
  928.  
  929. #if 0 /* not used */
  930.     int
  931. gui_mch_same_font(GuiFont f1, GuiFont f2)
  932. {
  933.     D("gui_mch_same_font");
  934. }
  935. #endif
  936.  
  937.     void
  938. gui_mch_free_font(GuiFont font)
  939. {
  940.     if (font)
  941.     D("gui_mch_free_font");
  942. }
  943.  
  944. #define RGB(a, b, c) ((a && 0xff) * 0x10000 + (b * 0xff) * 0x100 + (c & 0xff))
  945.  
  946.     guicolor_T
  947. gui_mch_get_color(char_u *name)
  948. {
  949.     typedef struct guicolor_tTable
  950.     {
  951.     char        *name;
  952.     unsigned long    color;
  953.     } guicolor_tTable;
  954.  
  955.     static guicolor_tTable table[] =
  956.     {
  957.     {"Grey",    0},
  958.     {"Black",    1},
  959.     {"DarkBlue",    2},
  960.     {"DarkGreen",    3},
  961.     {"DarkCyan",    4},
  962.     {"DarkRed",    5},
  963.     {"DarkMagenta",    6},
  964.     {"Brown",    7},
  965.     {"Gray",    8},
  966.     {"Grey",    9},
  967.     {"LightGray",    10},
  968.     {"LightGrey",    11},
  969.     {"DarkGray",    12},
  970.     {"DarkGrey",    13},
  971.     {"Blue",    14},
  972.     {"LightBlue",    15},
  973.     {"Green",    16},
  974.     {"LightGreen",    17},
  975.     {"Cyan",    18},
  976.     {"LightCyan",    19},
  977.     {"Red",        20},
  978.     {"LightRed",    21},
  979.     {"Magenta",    22},
  980.     {"LightMagenta",23},
  981.     {"Yellow",    24},
  982.     {"LightYellow",    25},    /* TODO: add DarkYellow */
  983.     {"White",    26},
  984.     {"SeaGreen",    27},
  985.     {"Orange",    28},
  986.     {"Purple",    30},
  987.     {"SlateBlue",    31},
  988.     {"grey90",    32},
  989.     {"grey95",    33},
  990.     {"grey80",    34},
  991.     {NULL, NULL},
  992.     };
  993.  
  994.     guicolor_T color = (guicolor_T)-1;
  995.  
  996.     int i;
  997.  
  998.     for (i = 0; table[i].name != NULL;i++)
  999.     {
  1000.     if (stricmp(name, table[i].name) == 0)
  1001.         color = table[i].color;
  1002.     }
  1003.  
  1004.     if (color == -1)
  1005.     {
  1006.     char **looky = NULL;
  1007.  
  1008.     color = strtol((char*)name, looky, 10);
  1009.     if (looky)
  1010.     {
  1011.         printf("invalid number \n");
  1012.         color = 1;
  1013.     }
  1014.     }
  1015.  
  1016.     return color;
  1017. }
  1018.  
  1019.     void
  1020. gui_mch_set_colors(guicolor_T fg, guicolor_T bg)
  1021. {
  1022.     if (fg == 0)
  1023.     {
  1024.     fg = 1;
  1025.     }
  1026.     SetABPenDrMd(gui.window->RPort, fg, bg, JAM2);
  1027. }
  1028.  
  1029.     void
  1030. gui_mch_set_fg_color(guicolor_T color)
  1031. {
  1032.     if (color == 0)
  1033.     {
  1034.     color = 1; /* vim sends 0 as default color which is ALWAYS the
  1035.               background on the amiga scrolling with colours as the
  1036.               background is a very bad idea on slow machines*/
  1037.     }
  1038.     SetAPen(gui.window->RPort, color);
  1039.     SetDrMd(gui.window->RPort, JAM2);
  1040. }
  1041.  
  1042.     void
  1043. gui_mch_set_bg_color(guicolor_T color)
  1044. {
  1045.     SetBPen(gui.window->RPort, color);
  1046. }
  1047.  
  1048.     void
  1049. gui_mch_draw_string(int row, int col, char_u *s, int len, int flags)
  1050. {
  1051.     switch(flags)
  1052.     {
  1053.     case 0:
  1054.         Move(gui.window->RPort, posWidthCharToPoint(col), posHeightCharToPoint(row));
  1055.         Text(gui.window->RPort, s, len);
  1056.         break;
  1057.     case DRAW_TRANSP:
  1058.         SetDrMd(gui.window->RPort, INVERSVID);
  1059.         Move(gui.window->RPort, posWidthCharToPoint(col), posHeightCharToPoint(row));
  1060.         Text(gui.window->RPort, s, len);
  1061.         break;
  1062.     case DRAW_BOLD:
  1063.         Move(gui.window->RPort, posWidthCharToPoint(col), posHeightCharToPoint(row));
  1064.         Text(gui.window->RPort, s, len);
  1065.         SetDrMd(gui.window->RPort, JAM1);
  1066.         Move(gui.window->RPort, posWidthCharToPoint(col), posHeightCharToPoint(row));
  1067.         Draw(gui.window->RPort, posWidthCharToPoint(col+len), posHeightCharToPoint(row));
  1068.         SetDrMd(gui.window->RPort, JAM2);
  1069.         break;
  1070.     case DRAW_UNDERL:
  1071.         Move(gui.window->RPort, posWidthCharToPoint(col), posHeightCharToPoint(row));
  1072.         Text(gui.window->RPort, s, len);
  1073.         Move(gui.window->RPort, posWidthCharToPoint(col)+1, posHeightCharToPoint(row));
  1074.         Text(gui.window->RPort, s, len);
  1075.         break;
  1076.     }
  1077. }
  1078.  
  1079.     int
  1080. gui_mch_haskey(char_u *name)
  1081. {
  1082.     int i;
  1083.  
  1084.     D("gui_mch_haskey");
  1085.  
  1086.     for (i = 0; special_keys[i].vim_code1 != NUL; i++)
  1087.     if (name[0] == special_keys[i].vim_code0 &&
  1088.         name[1] == special_keys[i].vim_code1)
  1089.         return OK;
  1090.     return FAIL;
  1091. }
  1092.  
  1093.     void
  1094. gui_mch_beep(void)
  1095. {
  1096.     D("gui_mch_beep");
  1097. }
  1098.  
  1099.     void
  1100. gui_mch_flash(int msec)
  1101. {
  1102.     D("gui_mch_flash");
  1103. }
  1104.  
  1105.     void
  1106. gui_mch_invert_rectangle( int r, int c, int nr, int nc)
  1107. {
  1108.     printf("gui_mch_invert_rectangle %d %d %d %d\n", r, c, nr, nc);
  1109. }
  1110.  
  1111.     void
  1112. gui_mch_iconify(void)
  1113. {
  1114.     D("gui_mch_iconify");
  1115. }
  1116.  
  1117. #if defined(FEAT_EVAL) || defined(PROTO)
  1118. /*
  1119.  * Bring the Vim window to the foreground.
  1120.  */
  1121.     void
  1122. gui_mch_set_foreground()
  1123. {
  1124.     D("gui_mch_set_foreground");
  1125. }
  1126. #endif
  1127.  
  1128.     void
  1129. gui_mch_settitle(char_u  *title, char_u  *icon)
  1130. {
  1131.     D("gui_mch_settitle");
  1132. }
  1133.  
  1134.     void
  1135. gui_mch_stop_blink(void)
  1136. {
  1137.     gui_undraw_cursor();
  1138.     D("gui_mch_stop_blink");
  1139. }
  1140.  
  1141.     void
  1142. gui_mch_start_blink(void)
  1143. {
  1144.     gui_update_cursor(FALSE, FALSE);
  1145.     D("gui_mch_start_blink");
  1146. }
  1147.  
  1148.     void
  1149. gui_mch_draw_hollow_cursor(guicolor_T color)
  1150. {
  1151.     drawBox(DB_NotFilled, gui.col, gui.row, color);
  1152. }
  1153.  
  1154.     void
  1155. gui_mch_draw_part_cursor( int col, int row, guicolor_T color)
  1156. {
  1157.     D("gui_mch_part_cursor");
  1158.     drawBox(DB_Filled, col, row, color);
  1159. }
  1160.  
  1161.     void
  1162. gui_mch_update(void)
  1163. {
  1164.     checkEventHandler();
  1165.     return ;
  1166. }
  1167.  
  1168.     int
  1169. gui_mch_wait_for_chars(int wtime)
  1170. {
  1171.     assert(wtime != 0);
  1172.     return charEventHandler(wtime);
  1173. }
  1174.  
  1175.     void
  1176. gui_mch_flush(void)
  1177. {
  1178. }
  1179.  
  1180.     void
  1181. gui_mch_clear_block(int row1, int col1, int row2, int col2)
  1182. {
  1183.     register int start;
  1184.  
  1185.     /* TODO: this isn't using "col2"! */
  1186.     for (start = row1; start < row2; start ++)
  1187.     {
  1188.     Move(gui.window->RPort, 0, posHeightCharToPoint(start));
  1189.     gui_mch_set_fg_color(0);
  1190.     gui_mch_set_bg_color(0);
  1191.     ClearEOL(gui.window->RPort);
  1192.     }
  1193. }
  1194.  
  1195.     void
  1196. gui_mch_clear_all(void)
  1197. {
  1198.     SetRast(gui.window->RPort, 0);
  1199.     refreshBorder();
  1200.     D("gui_mch_clear_all");
  1201. }
  1202.  
  1203.     void
  1204. gui_mch_delete_lines(int row, int num_lines)
  1205. {
  1206.     gui_clear_block(row, 0, row + num_lines, Columns - 1);
  1207.     /* changed without checking! */
  1208.     ScrollRaster(gui.window->RPort,
  1209.         posWidthCharToPoint(gui.scroll_region_left),
  1210.         characterHeight * num_lines,
  1211.         posWidthCharToPoint(gui.scroll_region_left),
  1212.         posHeightCharToPoint(row - 1) + 2,
  1213.         posWidthCharToPoint(gui.scroll_region_right + 1),
  1214.         posHeightCharToPoint(gui.scroll_region_bot) + 3);
  1215. }
  1216.  
  1217.     void
  1218. gui_mch_insert_lines(int row, int num_lines)
  1219. {
  1220.     SetABPenDrMd(gui.window->RPort, 0, 0, JAM2);
  1221.     /* changed without checking! */
  1222.     ScrollRaster(gui.window->RPort,
  1223.         posWidthCharToPoint(gui.scroll_region_left),
  1224.         -characterHeight*num_lines,
  1225.         posWidthCharToPoint(gui.scroll_region_left),
  1226.         posHeightCharToPoint(row-1)+2,
  1227.         posWidthCharToPoint(gui.scroll_region_right + 1),
  1228.         posHeightCharToPoint(gui.scroll_region_bot-num_lines+1)+1);
  1229.  
  1230.     gui_clear_block(row, gui.scroll_region_left,
  1231.                     row + num_lines, gui.scroll_region_right);
  1232. }
  1233.  
  1234.     void
  1235. gui_mch_enable_menu(int flag)
  1236. {
  1237.     D("gui_mch_enable_menu");
  1238. }
  1239.  
  1240.     void
  1241. gui_mch_set_menu_pos(int x, int y, int w, int h)
  1242. {
  1243.     D("gui_mch_set_menu_pos");
  1244. }
  1245.  
  1246.     void
  1247. gui_mch_destroy_menu(vimmenu_T *menu)
  1248. {
  1249.     D("gui_mch_destroy_menu");
  1250.     ClearMenuStrip(gui.window);
  1251. }
  1252.  
  1253.     void
  1254. gui_mch_menu_grey(vimmenu_T *menu, int grey)
  1255. {
  1256.     D("gui_mch_menu_grey");
  1257. }
  1258.  
  1259.     void
  1260. gui_mch_menu_hidden(vimmenu_T *menu, int hidden)
  1261. {
  1262.     D("gui_mch_menu_hidden");
  1263.     ClearMenuStrip(gui.window);
  1264. }
  1265.  
  1266.     void
  1267. gui_mch_draw_menubar(void)
  1268. {
  1269.     D("gui_mch_draw_menubar");
  1270.     SetMenuStrip(gui.window, gui.menu);
  1271. }
  1272.  
  1273.     static void
  1274. AmigaError(const char *string)
  1275. {
  1276.     static struct IntuiText pos = { 3, 0, JAM2, 17, 5, NULL, "Cancel", NULL} ;
  1277.     static struct IntuiText neg = { 3, 0, JAM2, 17, 5, NULL, "Cancel", NULL} ;
  1278.     static struct IntuiText message = { 3, 0, JAM2, 17, 5, NULL, NULL, NULL} ;
  1279.     static char *strptr = 0;
  1280.  
  1281.     if (strptr)
  1282.     free(strptr);
  1283.     strptr = malloc(strlen(string)+1);
  1284.  
  1285.     message.IText = strptr;
  1286.     strcpy(strptr, string);
  1287.  
  1288.     AutoRequest(NULL, &message, &pos, &neg, 0, 0, 300, 300);
  1289. }
  1290.  
  1291.     int
  1292. clip_mch_own_selection(VimClipboard *cbd)
  1293. {
  1294.     D("clib_mch_own_selection");
  1295.     return OK;
  1296. }
  1297.  
  1298.     void
  1299. mch_setmouse(int  on)
  1300. {
  1301. }
  1302.  
  1303. /*
  1304.  * Get current y mouse coordinate in text window.
  1305.  * Return -1 when unknown.
  1306.  */
  1307.     int
  1308. gui_mch_get_mouse_x()
  1309. {
  1310.     /* TODO */
  1311.     return -1;
  1312. }
  1313.  
  1314.     int
  1315. gui_mch_get_mouse_y()
  1316. {
  1317.     /* TODO */
  1318.     return -1;
  1319. }
  1320.  
  1321.     void
  1322. gui_mch_setmouse(x, y)
  1323.     int        x;
  1324.     int        y;
  1325. {
  1326.     /* TODO */
  1327. }
  1328.  
  1329.     void
  1330. gui_mch_show_popupmenu(vimmenu_T *menu)
  1331. {
  1332.     /* TODO */
  1333. }
  1334.  
  1335.     void
  1336. clip_mch_lose_selection(VimClipboard *cbd)
  1337. {
  1338.     D("clip_mch_lose_selecction");
  1339. }
  1340.  
  1341.     void
  1342. clip_mch_request_selection(VimClipboard *cbd)
  1343. {
  1344.     D("clip_mch_requst_selection");
  1345. }
  1346.  
  1347.     void
  1348. clip_mch_set_selection(VimClipboard *cbd)
  1349. {
  1350. }
  1351.  
  1352.     long_u
  1353. gui_mch_get_rgb(guicolor_T pixel)
  1354. {
  1355.     unsigned long  color;
  1356.  
  1357.     color = GetRGB4(gui.window->WScreen->ViewPort.ColorMap, pixel);
  1358.     return ((color & 0xf00) << 12) + ((color & 0x0f0) << 8)
  1359.                              + ((color & 0x00f) << 4);
  1360. }
  1361.  
  1362. #endif /* USE_AMIGA_GUI*/
  1363.